package com.meida.module.system.provider.service.impl;


import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.meida.common.constants.CommonConstants;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaDelete;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.mybatis.query.CriteriaUpdate;
import com.meida.common.utils.ApiAssert;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.utils.RedisUtils;
import com.meida.module.system.client.entity.SysDict;
import com.meida.module.system.client.entity.SysDictData;
import com.meida.module.system.provider.mapper.SysDictMapper;
import com.meida.module.system.provider.service.SysDictDataService;
import com.meida.module.system.provider.service.SysDictService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 字典接口实现
 *
 * @author flyme
 */
@Slf4j
@Service
public class SysDictServiceImpl extends BaseServiceImpl<SysDictMapper, SysDict> implements SysDictService {

    @Resource
    private SysDictDataService dictDataService;
    @Resource
    private RedisUtils redisUtils;

    @Override
    public List<SysDict> selectAll() {
        CriteriaQuery<SysDict> cq = new CriteriaQuery(SysDict.class);
        return list(cq.orderByAsc("sortOrder"));
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public SysDict findByType(String type) {
        CriteriaQuery<SysDict> cq = new CriteriaQuery(SysDict.class);
        cq.eq("dicType", type);
        List<SysDict> list = list(cq);
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public List<SysDict> search(String key) {
        CriteriaQuery<SysDict> cq = new CriteriaQuery(SysDict.class);
        return list(cq.like("dicTitle", key).or().like("dicType", key));
    }

    @Override
    public void initDictRedis() {
        List<String> dictKeys = new ArrayList<>();
        Map<Object, Object> dictDataMap = new HashMap<>();
        List<SysDict> dictList = list();
        if (ObjectUtils.isNotEmpty(dictList)) {
            dictList.forEach(dict -> {
                String dictType = dict.getDicType();
                List<EntityMap> dictDataList = dictDataService.selectByDictId(dict.getDictId());
                if (ObjectUtils.isNotEmpty(dictDataList)) {
                    dictDataMap.put(dictType, dictDataList);
                }
            });
            redisUtils.delByProjectName("DICT_DATA");
            redisUtils.setProjectMap("DICT_DATA", dictDataMap);
            log.info("初始化字典####################" + dictKeys.size());
        }
    }


    /**
     * 根据code查询
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public List<EntityMap> selectByCode(String dicType) {
        CriteriaQuery cq = new CriteriaQuery(SysDict.class);
        SysDict dict = getOne(cq.eq(true, "dicType", dicType), false);
        return dictDataService.selectByDictId(dict.getDictId());
    }

    @Override
    public Map<Object, Object> initDict() {
        Map<Object, Object> dataMaps = redisUtils.getMapByProject("DICT_DATA");
        return dataMaps;
    }


    @Override
    public ResultBody beforeAdd(CriteriaSave cs, SysDict dict, EntityMap extra) {
        String dictTitle = dict.getDicTitle();
        ApiAssert.isNotEmpty("字典分类不能为空", dictTitle);
        SysDict prodCategory = getDict(dictTitle);
        ApiAssert.isEmpty("分类已存在", prodCategory);
        Long parentId = FlymeUtils.isEmpty(dict.getParentId()) ? 0L : dict.getParentId();
        SysDict parent = getById(parentId);
        Integer count;
        CriteriaQuery cq = new CriteriaQuery(SysDict.class);
        if (parentId.equals(0L)) {
            count = count(cq.eq("parentId", cs.getParams("parentId")));
        } else {
            count = count(cq.eq("parentId", parent.getDictId()));
        }
        BigDecimal sortOrder = FlymeUtils.getBigDecimal(new BigDecimal(count), "0").add(new BigDecimal(1));
        dict.setAllowDel(CommonConstants.ENABLED);
        dict.setParentId(parentId);
        dict.setSortOrder(sortOrder);
        return ResultBody.ok();
    }

    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public SysDict getDict(String dictTitle) {
        CriteriaQuery<SysDict> cq = new CriteriaQuery(SysDict.class);
        cq.eq(true, "dicTitle", dictTitle);
        return getOne(cq);
    }


    @Override
    public ResultBody beforeEdit(CriteriaUpdate<SysDict> cu, SysDict sysDict,EntityMap extra) {
        SysDict dict = cu.getEntity(entityClass);
        String dictTitle = dict.getDicTitle();
        ApiAssert.isNotEmpty("字典分类不能为空", dictTitle);
        SysDict prodCategory = getDict(dictTitle);
        ApiAssert.isEmpty("分类已存在", prodCategory);
        return super.beforeEdit(cu, sysDict,extra);
    }

    @Override
    public ResultBody beforeDelete(CriteriaDelete<SysDict> cd) {
        CriteriaQuery cq = new CriteriaQuery(SysDictData.class);
        int n = dictDataService.count(cq.eq("dictId", cd.getIdField()));
        if (n > 0) {
            return ResultBody.failed("请先删除子节点");
        }
        return super.beforeDelete(cd);
    }
}